/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "ui终端视图.h"


#include "框架/工作区/工作区.h"
#include "物体编辑/物体编辑.h"
#include "物体管理/渲染物体管理.h"

#include <Context/当前默认操作数据.h>

#include <node后端.h>
#include <字符串/str_分割.h>


std::set<C_终端视图*> C_终端视图::g终端视图;




static void f_树形框项布局(C_Widget* self, C_Widget** w, uint32 num) {
	S_Object* item = (S_Object*)self->m_UserData;

	float32 组件大小 = self->m_Size.y;
	for (uint32 i = 0; i < num; ++i) {
		w[i]->f_setSize({ 组件大小, 组件大小 });
	}
	
	if (item) {
		if (item->m_是否展开) {
			w[0]->m_ICO = u"下";
		}
		else {
			w[0]->m_ICO = u"播放";
		}
		switch (item->m_Type) {
			case E_物体类型::t_网格物体:
			case E_物体类型::t_多边形:
				w[1]->m_ICO = u"物体";
				break;
			case E_物体类型::t_网格缓存:
				w[1]->m_ICO = u"四边顶点";
				break;
			case E_物体类型::t_虚拟体:
				w[1]->m_ICO = u"立体线框";
				break;
			case E_物体类型::t_摄像机:
				w[1]->m_ICO = u"font-449";
				break;
			case E_物体类型::t_物理体:
				w[1]->m_ICO = u"planet32";
				break;

			case E_物体类型::t_渲染世界:
				w[1]->m_ICO = u"世界";
				break;
			case E_物体类型::t_渲染层:
				w[1]->m_ICO = u"layers_1";
				break;
			case E_物体类型::t_渲染物体:
				w[1]->m_ICO = u"物体";
				break;
			default:
				w[1]->m_ICO = u"包";
				break;
		}


		uint32 按钮数量 = 4;
		switch (item->m_Type) {
			case E_物体类型::t_虚拟体:
			case E_物体类型::t_网格物体:
			case E_物体类型::t_多边形:
				w[3]->m_ICO = item->m_显示 ? u"可视" : u"";
				w[4]->m_ICO = item->m_可拾取 ? u"选择" : u"空选择";
				break;
			case E_物体类型::t_网格缓存:
				w[3]->m_ICO = u"";
				break;

			case E_物体类型::t_渲染世界:
				w[3]->m_ICO = item->m_显示 ? u"加" : u"加";
				w[4]->m_ICO = item->m_显示 ? u"减" : u"减";
				break;

			case E_物体类型::t_渲染层: {
				按钮数量 = 2;
				break;
			}
			case E_物体类型::t_渲染物体: {
				//w[3]->f_setSize({ 组件大小 * 8, 组件大小 });
				//w[4]->f_setSize({ 组件大小 * 8, 组件大小 });
				break;
			}
			default:
				w[3]->m_ICO = u"";
				w[4]->m_ICO = u"";
				break;
		}


		w[2]->m_WName = item->m_Name;


		float32 推进 = item->m_层深度 * self->m_Size.y;
		vec2 大小 = { self->m_Size.x, self->m_Size.y };
		大小.x = max(self->m_Size.y * 按钮数量 + 推进, 大小.x);

		f_HBOX布局({ 推进,0 }, 大小, w, num);
	}
	else {
		self->m_ICO = u"下";
	}
}

void on_终端输入一行回调(C_Widget* r, const std::u16string& text, E_字符输入类型 输入类型) {
	std::string code;
	C_文本框& edit = *dynamic_cast<C_文本框*>(r);
	C_终端视图& box = *dynamic_cast<C_终端视图*>(r->m_父部件);


	int32 包裹行数 = 1;
	if (输入类型 == E_字符输入类型::e_拆分行) {
		包裹行数 = 2;
	}


	bool 累积 = true;
	if (box.m_当前编辑代码段开始行 >= 0) {
		累积 = false;
		code = f_ui_取编辑框包裹文本(&edit, box.m_当前编辑代码段开始行);
	}
	else {
		code = f_str_u16_to_u8(text);
	}
	if(code.empty()) return;


	static int32 取消代码块输入 = 0;
	if (text.empty()) {
		++取消代码块输入;

		if (取消代码块输入 >= 2) {
			box.m_当前编辑代码段开始行 = -1;
			取消代码块输入 = 0;
			return;
		}
	}

	int32 result = f_node_执行lua脚本(box.m_Lua环境, code, 累积);
	//std::cout<<"box.m_当前编辑代码段开始行 = "<<box.m_当前编辑代码段开始行<<std::endl;
	
	
	switch (result) {
		case -1: {
			if(box.m_当前编辑代码段开始行 < 0) {
				box.m_当前编辑代码段开始行 = edit.m_光标坐标索引.y - 1;
				包裹行数 = 2;
			}
			break;
		}
		case 0:
		case 1:
		case 2: {
			if (code.size()) {
				S_着色文本块 文本块;
				文本块.m_一行 = f_str_string_to_u16(code);
				文本块.m_颜色 = std::vector<S_RGBA8UI>(文本块.m_一行.size(), {120,120,120,255});
				f_ui_文本编辑框插入行(&edit, 文本块, edit.m_光标坐标索引);
				f_ui_文本编辑框插入行(&edit, {}, {-1, -1});
			}
			box.m_当前编辑代码段开始行 = -1;
			break;
		}
		default:
			break;
	}

	if (box.m_当前编辑代码段开始行 >= 0) {
		f_ui_添加文本包裹绘制(&edit, box.m_当前编辑代码段开始行, 包裹行数);
	}

}

bool on_终端输入字符回调(C_Widget* r, wchar_t text) {
	C_文本框& edit = *dynamic_cast<C_文本框*>(r);

	auto& doc = f_ui_get编辑框文本块(&edit);
	auto 当前词 = f_ui_取编辑框光标行文本(&edit);

	std::vector<std::string> startCharacters = {
		// 空白字符（最高优先级）
		" ", "\t", "\n", "\r",
		// 语法符号
		"=", "+", "-", "*", "/", "%", "^",
		"==", "~=", ">", "<", ">=", "<=",
		"(", ")", "{", "}", "[", "]",
		",", ";", ":", 
		// 字符串边界符
		"'", "\"", //"[[", "]]", ".",
		// 注释符号
		//"--", "--[[", "]]--"
	};

	std::vector<uint32> 末尾位置;

	for (const auto& e : startCharacters) {
		//auto pos_空格 = 当前词.find_last_of(e);
		auto pos_空格 = f_str_find_词最后出现位置(当前词, e, false);
		if (pos_空格 != -1) {
			末尾位置.push_back(pos_空格 + 1);
		}
	}

	std::sort(末尾位置.begin(), 末尾位置.end());

	std::string word;
	if (末尾位置.size()) {
		word = 当前词.substr(末尾位置.back());
	}
	else {
		word = 当前词;
	}


	// 提取候选词
	std::vector<std::string> 提示;
	auto pos_点 = f_str_find_词最后出现位置(word, ".", false);
	if (pos_点 > 0) {
		提示 = f_node_成员代码补全(word, doc, 2);
	}
	else {
		提示 = f_node_代码提示补全(word, doc, 1);
	}
	f_ui_置入编辑框输入提示文本(&edit, 提示);
	
	

	return false;
}



static E_事件是否传递 f_终端视图_滚轮视图(C_Widget* self, const S_鼠标& 鼠标) {
	auto& view = *self->f_get子组件(0);
	view.f_setW(self->m_Size.x);

	f_布局_纵向滚动值限度(view.m_Pos.y, self->m_Size.y, view.m_Size.y, C_Widget::g_鼠标.lZ * 40);

	auto* 滚动条 = self->f_get子组件(1);
	f_ui_滚动条更新属性(滚动条);
	
	f_widget_更新绘制(self);
	return E_事件是否传递::e_事件传递_终止;
}

static void f_终端视图布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_终端视图& box = *static_cast<C_终端视图*>(self);

	vec2 size = self->m_Size;
	
	auto& doc = f_ui_get编辑框文本块(box.m_编辑框);
	auto* editbox = dynamic_cast<C_文本框*>(box.m_编辑框);

	float32 dpi = box.m_UIctx->m_DPI;
	float32 行高 = (editbox->m_字号 + editbox->m_行距) * dpi;

	int32 行开始偏移 = 0;
	//int32 有效行显示数量 = f_ui_Layout_行显示范围(self, 行高, doc.m_文本块.size(), 行开始偏移);
	//size.y = max(有效行显示数量 * 行高, size.y);
	size.y = max((doc.m_文本块.size() + 5) * 行高, size.y);

	box.m_编辑框->f_setSize(size);

	auto* 滚动条 = self->f_get子组件(1);
	f_布局_纵向滚动条(滚动条, self->m_Size, 0, size.y);

}

static void f_终端视图绘制(C_Widget* self, S_2D画布* 画布) {
	C_终端视图& box = *dynamic_cast<C_终端视图*>(self);
	box.m_背景 = f_vg_genConvex((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	
}
static void f_终端视图变换(C_Widget* self) {
	C_终端视图& box = *dynamic_cast<C_终端视图*>(self);
	float32 dpi = box.m_UIctx->m_DPI;

	auto ui_tree = self->f_get子组件(0);

	std::vector<S_2DConvexRect>	区域(1);
	std::vector<S_GPU内存块*>	形状(1);
	std::vector<S_2D颜色包>		颜色(1);
	std::vector<vec2>			位置(1);

	形状[0] = &(box.m_UIctx->m_Ctx.m_几何图形->m_平面矩形);
	区域[0] = {{}, self->m_Size, {1,0}};
	颜色[0] = S_UI主题::uic_深色;
	位置[0] = {};

	{
		auto* 滚动条 = box.f_get子组件(1);
		vec2 pos = 滚动条->m_Pos;
		S_2DConvexRect rect{};
		rect.size = 滚动条->m_Size;
		rect.radius = {dpi*5, dpi*5};
		形状.push_back(&(box.m_UIctx->m_Ctx.m_几何图形->m_平面圆角矩形));
		区域.push_back(rect);
		颜色.push_back(S_2D颜色包(S_UI主题::uic_滚动条));
		位置.push_back(pos);

		滚动条 = 滚动条->f_get子组件(0);

		rect.size = 滚动条->m_Size;
		if (滚动条->m_ColorA.m_颜色.a < 255) {
			rect.size -= rect.size.x * 0.6;
			pos += (滚动条->m_Size - rect.size) * 0.5;
		}
		
		rect.radius = {dpi*5, dpi*5};
		形状.push_back(&(box.m_UIctx->m_Ctx.m_几何图形->m_平面圆角矩形));
		区域.push_back(rect);
		颜色.push_back(滚动条->m_ColorA);
		位置.push_back(pos + 滚动条->m_Pos);
	}
	


	f_vg_tranform(*box.m_背景, 位置.size(), 位置.data());
	f_vg_drawConvex(*box.m_背景, 形状.size(), 形状.data(), 区域.data());
	f_vg_color(*box.m_背景, 颜色.size(), 颜色.data());
}

C_终端视图::C_终端视图(S_UI渲染环境& ctx) : C_Widget(&ctx) {
	f_widget_添加绘制画布(this);

	m_编辑框 = f_ui_创建文本编辑框(ctx);
	dynamic_cast<C_文本框*>(m_编辑框)->mf_行输入回调 = on_终端输入一行回调;
	dynamic_cast<C_文本框*>(m_编辑框)->mf_字符输入回调 = on_终端输入字符回调;

	auto 滚动条 = f_ui_创建滚动条(ctx, E_方向::e_纵向);
	f_ui_滚动条绑定属性(滚动条, &m_编辑框->m_Pos.y, m_编辑框->m_Size.y);

	f_添加子组件(m_编辑框);
	f_添加子组件(滚动条);


	m_Lua环境 = f_node_创建LUA环境();
	m_当前编辑代码段开始行 = -1;


	std::u16string 名称[5] = {
		u"版本: ",
		u"系统: ",
		u"架构: ",
		u"状态: ",
		u"trace: ",
	};
	std::string code[5] = {
		"jit.version",
		"jit.os",
		"jit.arch",
		"jit.status()",
		"jit.tracecount()",
	};
	for (uint32 i = 0; i < 4; ++i) {
		f_node_执行lua脚本(m_Lua环境, code[i], true);

		S_着色文本块 文本块;
		文本块.m_一行 = 名称[i] + f_str_string_to_u16(code[i]);
		文本块.m_颜色 = std::vector<S_RGBA8UI>(文本块.m_一行.size(), {120,120,120,255});
		f_ui_文本编辑框插入行(m_编辑框, 文本块, {-1, -1});
	}
	f_ui_文本编辑框插入行(m_编辑框, {}, {-1, -1});

	f_node_导入内部函数(m_Lua环境, {});

	g终端视图.insert(this);
}

C_终端视图::~C_终端视图() {
	
	f_node_销毁LUA环境(m_Lua环境);

	g终端视图.erase(this);
}


C_终端视图* f_终端视图_创建(S_UI渲染环境& ctx) {
	C_终端视图* box = new C_终端视图(ctx);

	box->m_属性栏 = f_创建属性边栏(ctx);
	box->m_状态条 = new C_状态条(ctx);

	box->mf_布局		= f_终端视图布局;
	box->mf_绘制		= f_终端视图绘制;
	box->mf_变换		= f_终端视图变换;
	box->mf_鼠标滚轮	= f_终端视图_滚轮视图;

	//auto 滚动框 = f_ui_创建滚动框(ctx, false, true, box);
	return box;
}










